#include "stdafx.h"
#include ".\connection.h"
#include "PoolMgr.h"
#include <mstcpip.h>
///////////////////////////////////////////////////////////////////////////////
// Namespace: Lumin::Win32
///////////////////////////////////////////////////////////////////////////////
namespace Lumin {
namespace Win32 {
 

///////////////////////////////////////////////////////////////////////////////
// CConnection
///////////////////////////////////////////////////////////////////////////////
CConnection::CConnection(const char* address,DWORD dwContext):m_skSocket(INVALID_SOCKET),m_dwContext(dwContext)
{
	m_nData = 0;
	m_pISocketListener = NULL;
	strcpy(m_szAddress,address);
}

CConnection::~CConnection(void)
{

}

void* CConnection::operator new(size_t objectSize)
{
	return CPoolMgr<CConnection>::GetInstance()->Allocate(objectSize);
}

void CConnection::operator delete(void *pObject, size_t /* bufferSize*/)
{
	CPoolMgr<CConnection>::GetInstance()->Free(pObject);
}

void CConnection::AttachSocket(SOCKET skSocket)
{
	if(m_skSocket == INVALID_SOCKET){
		m_skSocket = skSocket;
	}else{
		closesocket(m_skSocket);
		m_skSocket = skSocket;
	}
	SetNoFree();
}

void CConnection::Shutdown()
{
	if(m_skSocket != INVALID_SOCKET){
		::shutdown(m_skSocket,SD_SEND);
	}
}

void CConnection::AbortiveShutdown(){
	CloseSocket();
}

void CConnection::CloseSocket()
{
	if(DoFree()){
		if(m_skSocket != INVALID_SOCKET){
			::closesocket(m_skSocket);
			m_skSocket = INVALID_SOCKET;
		}
	}
}

void CConnection::SendPacket(ISerializeStream* pStream)
{
	DWORD write = 0;
	DWORD flags = 0;
	CIOContext* pIOContext = new CIOContext();
	pIOContext->stream = pStream;
	pIOContext->stream->AddRef();
	pIOContext->data.buf = pStream->GetData();
	pIOContext->data.len = pStream->GetSize();
	pIOContext->iop = WSA_IO_SEND;
	pIOContext->conn = this;

	if(SOCKET_ERROR == WSASend(m_skSocket, &pIOContext->data, 1, &write, flags, &pIOContext->overlapped, NULL)) 
	{
		if( ::GetLastError() != ERROR_IO_PENDING && 
			::GetLastError() != ERROR_SUCCESS )
		{
			Output("CConnection::SendPacket Error. ErrorID:%d",GetLastError());
		} 
	}
}

void CConnection::SendPacket(char* buffer,int len)
{
	::send(m_skSocket,buffer,len,0);
}

BOOL CConnection::PostRecv(CIOContext* pIOContext)
{
	DWORD ready = 0;
	DWORD flags = 0;
	if(pIOContext == NULL){
		pIOContext = new CIOContext();
		pIOContext->stream = CServer::Allocate();
		pIOContext->stream->AddRef();
	}
	pIOContext->data.buf = pIOContext->stream->GetData();
	pIOContext->data.len = CServer::StreamSize();
	pIOContext->iop = WSA_IO_RECV;
	pIOContext->conn = this;

	if(SOCKET_ERROR == ::WSARecv(m_skSocket,&pIOContext->data,1,&ready,&flags,&pIOContext->overlapped,NULL))
	{
		if(WSA_IO_PENDING != ::WSAGetLastError() ) {
			Output("CConnection::PostRecv Error.ErrorID:%d",GetLastError());
			return FALSE;
		} 
	}
	return TRUE;
}


char* CConnection::GetAddress()
{
	return m_szAddress;
}

bool CConnection::DoFree()
{
	return InterlockedExchange(&m_bSocketFree, TRUE) == FALSE;
}

void CConnection::SetNoFree()
{
	InterlockedExchange(&m_bSocketFree, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
// Namespace: Lumin::Win32
///////////////////////////////////////////////////////////////////////////////

} // End of namespace Win32
} // End of namespace Lumin 
